﻿using DaqConfigureTool.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;

namespace DaqConfigureTool.ViewModels
{

    public class JsonRpcRequest
    {
        //public string Jsonrpc { get; set; } = "2.0";
        [JsonPropertyName("method")]
        public object Method { get; set; }
        [JsonPropertyName("params")]
        public object Params { get; set; }
        [JsonPropertyName("id")]
        public int Id { get; set; }
    }

    

    public class JsonRpcResponse
    {
        //public string Jsonrpc { get; set; }
        [JsonPropertyName("id")]
        public int Id { get; set; }
        [JsonPropertyName("result")]
        public object Result { get; set; }
        [JsonPropertyName("error")]
        public object Error { get; set; }
    }

    // 接收服务器的响应
    
    public class DX2100 : DaqBase
    {
        public override async Task CloseAsync(CancellationToken token)
        {
            try
            {
                // 关闭连接
                await client?.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
            }
            catch (Exception ex) 
            {
                Debug.WriteLine(ex.Message);
            }
            client?.Dispose();
            client = null;
            isRunning = false;
        }

        public override async Task<bool> EnsureConnection(CancellationToken token)
        {
            if(client == null)
            {
                client = new ClientWebSocket();
            }
            
            if(client.State == WebSocketState.Open || client.State == WebSocketState.Connecting)
            {
                return true;
            }

            if(client.State == WebSocketState.Aborted)
            {
                client.Dispose();
                client = new ClientWebSocket();
            }

            if (Address == null) return false;
            var uri = new Uri($"ws://{Address}:8000/websocket");

            var clientTask = client?.ConnectAsync(uri, token);
            var timeOutTask = Task.Delay(2000, token);
            var completedTask = await Task.WhenAny(clientTask, timeOutTask);
            if(completedTask == timeOutTask)
            {
                token.ThrowIfCancellationRequested();
            }
            return true;
        }

        byte[] bufferResponse = new byte[1024000];
        private bool isRunning = false;
        private DateTime daqTime;
        public override async Task<int> FetchAsync(int timeout, CancellationToken token)
        {
            await EnsureConnection(token);
            if (!isRunning)
            {
                await SendRpcRequest("start", null, 0, token);
                try
                {
                    var response = await ReceiveRpcResponse(token);
                    if (response.Result.ToString() == "0")
                    {
                        isRunning = true;
                        daqTime = DateTime.Now;
                    }
                }
                catch(Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
                return 1;
            }
            else
            {
                WebSocketReceiveResult result;
                // 创建一个延迟任务，该任务将在超时时间后完成
                var delayTask = Task.Delay(timeout, token);

                CancellationTokenSource source = new();

                // 同时开始接收数据
                var receiveTask = client.ReceiveAsync(new ArraySegment<byte>(bufferResponse), source.Token);

                // 等待两个任务中的任何一个完成
                Task completedTask = await Task.WhenAny(receiveTask, delayTask);

                // 检查哪个任务完成
                if (completedTask == receiveTask)
                {
                    // 接收成功
                    result = await receiveTask;
                    var response = Encoding.UTF8.GetString(bufferResponse, 0, result.Count);
                    //Debug.WriteLine($"Received: {result.Count}");

                    int groupCount = bufferResponse[0] + (bufferResponse[1] << 8) + (bufferResponse[2] << 16) + (bufferResponse[3] << 24);
                    //int chCount = (result.Count - 4) / groupCount / 4;
                    //Debug.WriteLine($"chCount: {chCount}");
                    if (chCount != (result.Count - 4) / groupCount / 4)
                    {
                        Debug.WriteLine("数据错误");
                        return 1;
                    }

                    int index = 4;
                    //Random random = new Random();
                    for (int i = 0; i < groupCount; i++)
                    {
                        DaqMeasureData data = new DaqMeasureData();
                        daqTime = daqTime.AddMilliseconds(1);
                        data.Time = daqTime;
                        data.RawValue = new int[chCount];


                        for (int ch = 0; ch < chCount; ch++)
                        {
                            data.RawValue[ch] = bufferResponse[index] + (bufferResponse[index + 1] << 8) + (bufferResponse[index + 2] << 16) + (bufferResponse[index + 3] << 24);
                            //data.RawValue[ch] = (int)random.NextInt64(10, 100) + 3300;
                            //if(ch >= 48 && ch <= 55)
                            //{
                            //    data.RawValue[ch] = (int)random.NextInt64(10, 100) + 24000;
                            //}
                            index += 4;
                        }
                        //data.RawValue[56] = 33;
                        //if(data.RawValue[56] != 5600)
                        //Debug.WriteLine($"{chCount},{data.RawValue[56]}");
                        //Debug.WriteLine(string.Join(',', data.RawValue));
                        MeasureDataQueue.Enqueue(data);
                    }
                    return groupCount;
                }
                else if (completedTask == delayTask)
                {
                    source.Cancel();
                }

                return 1;
            }
        }

        public async Task SetSN(string sn, CancellationToken token)
        {
            await SendRpcRequest("set_sn", new string[] { sn }, 0, token);
            await ReceiveRpcResponse(token);
        }
        public async Task SetTime(CancellationToken token)
        {
            string time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            await SendRpcRequest("set_datetime", new string[] { time }, 0, token);
            await ReceiveRpcResponse(token);
        }
        public async Task SetBuzzer(bool state, CancellationToken token)
        {
            Debug.WriteLine(state);
            await SendRpcRequest("set_buzzer", new object[] { state }, 0, token);
            await ReceiveRpcResponse(token);
        }

        private int chCount = -1;
        public override async Task GetChannelsAsync(CancellationToken token, List<int>? whiteList = null)
        {
            await GetDaqSettings(token);
            var chs = new List<ChannelModel>();
            chCount = DaqSettings.Channels.Where(ch => ch.Status == true).Count();
            int index = 1;
            if(DaqSettings.Channels != null)
            {
                foreach (var ch in DaqSettings.Channels)
                {
                    if (!ch.Status) continue;
                    chs.Add(new ChannelModel
                    {
                        Type = DaqDevice.GetChannelType(ch.Unit),
                        Unit = ch.Unit,
                        RangeMax = 100,
                        RangeMin = 0,
                        Index = index++,
                        IsEnabled = ch.Status,
                        Color = ch.Color,
                        Name = ch.Alias,
                        Digits = ch.Digits
                    });
                }
            }
            MeasureData.Channels = [.. chs];
        }

        public override Task<double> GetSampleRateAsync(CancellationToken token)
        {
            return Task.FromResult(0.001);
        }

        public async Task SendRpcRequest(string methodName, object parameters, int id, CancellationToken token)
        {
            await EnsureConnection(token);
            // 发送JSON-RPC请求
            var request = new JsonRpcRequest
            {
                Method = methodName,
                Params = parameters,
                Id = id
            };
            var json = JsonSerializer.Serialize(request);
            var buffer = Encoding.UTF8.GetBytes(json);
            var segment = new ArraySegment<byte>(buffer);
            await client?.SendAsync(segment, WebSocketMessageType.Text, true, CancellationToken.None);
        }

        public async Task<JsonRpcResponse> ReceiveRpcResponse(CancellationToken token)
        {
            await EnsureConnection(token);
            var result = await client.ReceiveAsync(new ArraySegment<byte>(bufferResponse), CancellationToken.None);
            var response = Encoding.UTF8.GetString(bufferResponse, 0, result.Count);
            Debug.WriteLine(response);
            return JsonSerializer.Deserialize<JsonRpcResponse>(response);
        }

        private ClientWebSocket client;

        private async Task<byte[]> ReceiveAsync(TimeSpan timeout, CancellationToken cancellationToken)
        {
            WebSocketReceiveResult result;
            // 创建一个延迟任务，该任务将在超时时间后完成
            var delayTask = Task.Delay(timeout, cancellationToken);

            // 同时开始接收数据
            var receiveTask = client.ReceiveAsync(new ArraySegment<byte>(bufferResponse), CancellationToken.None);

            // 等待两个任务中的任何一个完成
            Task completedTask = await Task.WhenAny(receiveTask, delayTask);

            // 检查哪个任务完成
            if (completedTask == receiveTask)
            {
                // 接收成功
                result = await receiveTask;
                byte[] array = new byte[result.Count];
                Debug.WriteLine(result.Count);
                Array.Copy(bufferResponse.ToArray(), array, result.Count);
                return array;
            }
            else if (completedTask == delayTask)
            {
                cancellationToken.ThrowIfCancellationRequested();
            }
            return null;
        }

        public static string TruncateUtf8String(string input, int maxLength)
        {
            byte[] encodedBytes = Encoding.UTF8.GetBytes(input);

            // 如果原始字符串转换后的长度超过最大长度，则进行截断
            if (encodedBytes.Length > maxLength)
            {
                // 使用 StringBuilder 来构建截断后的字符串
                var sb = new System.Text.StringBuilder();
                int bytesWritten = 0;

                for (int i = 0; i < input.Length; i++)
                {
                    char c = input[i];
                    byte[] currentCharBytes = Encoding.UTF8.GetBytes(c.ToString());

                    // 检查添加当前字符后是否超过了最大长度
                    if (bytesWritten + currentCharBytes.Length <= maxLength)
                    {
                        sb.Append(c);
                        bytesWritten += currentCharBytes.Length;
                    }
                    else
                    {
                        // 如果添加当前字符会导致长度超过最大长度，且当前字符是多字节字符，则跳过该字符
                        if (currentCharBytes.Length > 1)
                        {
                            continue;
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                // 返回截断后的字符串
                return sb.ToString();
            }

            // 如果不需要截断，则直接返回原始字符串
            return input;
        }

        public override async Task SendDaqSettings(CancellationToken token)
        {
            if (DaqSettings == null)
            {
                return;
            }
            foreach(var ch in DaqSettings.Channels)
            {
                ch.Alias = TruncateUtf8String(ch.Alias, 32 - 1);
                ch.Unit = TruncateUtf8String(ch.Unit, 16 - 1);
            }
            string str = JsonSerializer.Serialize(DaqSettings);
            await SendRpcRequest("set_daq_info", new string[] { str }, 0, token);
            Debug.WriteLine("设置DAQ参数：" + str);
            await Task.Delay(5000);
        }

        private async Task GetDaqSettings(CancellationToken token)
        {
            await SendRpcRequest("get_daq_info", null, 0, token);

            // 接收服务器的响应
            //var result = await client.ReceiveAsync(new ArraySegment<byte>(bufferResponse), CancellationToken.None);

            for (int i = 0; i < 10; i++)
            {
                try
                {
                    var result = await ReceiveAsync(TimeSpan.FromMilliseconds(1000), new CancellationToken());
                    if (result == null || result.Length == 0) continue;
                    var response = Encoding.UTF8.GetString(bufferResponse, 0, result.Length);
                    Debug.WriteLine($"Received {response}");
                    JsonRpcResponse r = JsonSerializer.Deserialize<JsonRpcResponse>(response);
                    DaqSettings = JsonSerializer.Deserialize<DaqSettings>(r.Result.ToString());
                    break;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"Error: {ex.Message}");
                }
            }

            if (DaqSettings != null && DaqSettings.Channels != null)
            {
                int index = 1;
                foreach (var ch in DaqSettings.Channels)
                {
                    ch.Index = index;
                    index++;
                }
            }
        }

        public override async Task OpenAsync(CancellationToken token)
        {
        }
        
        private async Task SendDiscoveringPacket()
        {
            try
            {
                // 获取所有网络接口
                var interfaces = NetworkInterface.GetAllNetworkInterfaces();

                List<Task> tasks = new List<Task>();

                foreach (var interfaceItem in interfaces)
                {
                    if (interfaceItem.OperationalStatus == OperationalStatus.Up &&
                        interfaceItem.NetworkInterfaceType != NetworkInterfaceType.Loopback)
                    {
                        // 获取接口的IPv4地址
                        var properties = interfaceItem.GetIPProperties();
                        var unicastAddresses = properties.UnicastAddresses;
                        IPAddress ipToUse = null;
                        foreach (var address in unicastAddresses)
                        {
                            if (address.Address.AddressFamily == AddressFamily.InterNetwork)
                            {
                                ipToUse = address.Address;
                                break;
                            }
                        }

                        if (ipToUse == null)
                        {
                            continue;
                        }

                        // 创建UdpClient实例
                        using (UdpClient client = new UdpClient())
                        {
                            // 绑定到特定的本地地址和端口
                            client.Client.Bind(new IPEndPoint(ipToUse, 50001)); // 绑定到ipToUse，端口设为0表示由操作系统选择一个可用的端口

                            // 设置广播权限
                            client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);

                            // 定义广播地址和端口
                            IPEndPoint endPoint = new IPEndPoint(IPAddress.Broadcast, 50000); // 广播地址和端口号

                            // 发送的数据
                            byte[] data = { 0x01, 0x02, 0x04, 0x08 };

                            // 异步发送数据
                            tasks.Add(client.SendAsync(data, data.Length, endPoint));

                            Debug.WriteLine($"Broadcast message will be sent from interface: {interfaceItem.Name} with IP: {ipToUse}");
                        }
                    }
                }

                // 等待所有任务完成
                await Task.WhenAll(tasks);

                Debug.WriteLine("All broadcast messages sent.");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error: {ex.Message}");
            }
        }

        private static async Task SendBroadcastDataAsync(UdpClient client, IPAddress interfaceAddress)
        {
            IPEndPoint remoteEndpoint = new IPEndPoint(IPAddress.Broadcast, 50000);
            byte[] data = [0x01, 0x02, 0x04, 0x08];
            await client.SendAsync(data, data.Length, remoteEndpoint);
            Debug.WriteLine($"Sent broadcast data from interface: {interfaceAddress}");
        }

        private static async Task<byte[]> ReceiveDataWithTimeoutAsync(UdpClient client, TimeSpan timeout, CancellationToken cancellationToken)
        {
            // 创建一个延迟任务，该任务将在超时时间后完成
            Task delayTask = Task.Delay(timeout, cancellationToken);

            // 同时开始接收数据
            Task<UdpReceiveResult> receiveTask = client.ReceiveAsync();

            // 等待两个任务中的任何一个完成
            Task completedTask = await Task.WhenAny(receiveTask, delayTask);

            UdpReceiveResult result;

            // 检查哪个任务完成
            if (completedTask == receiveTask)
            {
                // 接收成功
                result = await receiveTask;
                return result.Buffer;
            }
            else if (completedTask == delayTask)
            {
                cancellationToken.ThrowIfCancellationRequested();
            }
            return null;
        }


        private static List<UdpClient> _udpClients = new List<UdpClient>();
        private static List<Task<byte[]>> _tasks = [];


        public override async Task<List<string>> SearchAsync(CancellationToken token)
        {
            List<string> list = [];
            try
            {
                // 获取所有网络接口
                var interfaces = NetworkInterface.GetAllNetworkInterfaces();
                List<UdpClient> clients = [];
                _tasks = [];
                // 遍历所有网络接口并创建UdpClient实例
                foreach (var interfaceItem in interfaces)
                {
                    if (interfaceItem.OperationalStatus == OperationalStatus.Up &&
                        interfaceItem.NetworkInterfaceType != NetworkInterfaceType.Loopback)
                    {
                        var properties = interfaceItem.GetIPProperties();
                        var unicastAddresses = properties.UnicastAddresses;
                        foreach (var address in unicastAddresses)
                        {
                            if (address.Address.AddressFamily == AddressFamily.InterNetwork)
                            {
                                UdpClient client = new UdpClient();
                                clients.Add(client);
                                IPEndPoint localEndpoint = new IPEndPoint(address.Address, 50001);
                                client.Client.Bind(localEndpoint);
                                client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
                                _udpClients.Add(client);

                                // 发送广播数据
                                await SendBroadcastDataAsync(client, address.Address);
                                // 启动接收数据的任务
                                CancellationTokenSource cts = new();
                                // 启动接收数据的任务
                                _tasks.Add(ReceiveDataWithTimeoutAsync(client, TimeSpan.FromSeconds(1), cts.Token));
                            }
                        }
                    }
                }


                // 等待所有接收数据的任务完成
                await Task.WhenAll(_tasks);

                foreach (var client in clients)
                {
                    client.Dispose();
                }

                
                foreach (var task in _tasks)
                {
                    var array = task.Result;
                    if(array != null)
                    {
                        string str = Encoding.UTF8.GetString(array);
                        list.Add(str);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error: {ex.Message}");
            }
            return list;
        }

        public override async Task<bool> ModifyAddress(object address, CancellationToken token)
        {
            if (address is string[] array && array.Length == 2)
            {
                await SendRpcRequest("set_ip_address", array, 0, token);
                //var result = await ReceiveRpcResponse(token);
                return true;
            }
            return false;
        }

        public override async Task StopAsync(CancellationToken token)
        {
            try
            {
                await SendRpcRequest("stop", null, 0, token);
                await ReceiveRpcResponse(token);
            }
            catch { }
        }
    }
}
